/************************************************************************
 *
 * i8.h
 *
 * (c) Copyright 2001-2004 Analog Devices, Inc.  All rights reserved.
 * $Revision: 1.1 $
 ************************************************************************/

/* Support for 8-bit integer operations (4x8/8x8), including
 * arithmetic, packing and unpacking, combining and extracting. 
 */

#pragma once
#ifndef __NO_BUILTIN
#pragma system_header /* i8.h */
#endif

#ifndef __I8_DEFINED
#define __I8_DEFINED

#include <i16.h>

#ifdef __ADSPTS__

#ifndef _RAW_TYPES
#define _RAW_TYPES
typedef int           _raw32;
typedef long long int _raw64;
#endif

#endif /* __ADSPTS__ */


typedef _raw32  int4x8;
typedef _raw64  int8x8;


/* Some functions are available as builtins */
#if defined(__ADSPTS__) && !defined(__NO_BUILTIN)

#define add_i4x8  __builtin_add_4x8
#define sub_i4x8  __builtin_sub_4x8
#define sum_i4x8  __builtin_sum_4x8

#define compact_to_i4x8 __builtin_compact_to_i4x8
#define expand_i4x8 __builtin_expand_i4x8

#define add_i8x8  __builtin_add_8x8
#define sub_i8x8  __builtin_sub_8x8
#define mult_i8x8 __builtin_mult_i8x8
#define sum_i8x8  __builtin_sum_8x8

#define compose_64 __builtin_compose_64
#define low_32 __builtin_low_32
#define high_32 __builtin_high_32
#define part_extract __builtin_fext

#endif /* __ADSPTS__ && !__NO_BUILTIN */


#ifdef __cplusplus
extern "C" {
#endif

/*************************************************************************
 * Operations on int2x16: Two 16-bit integers in parallel
 *************************************************************************/

/* Addition:  add_i4x8({A,B,C,D}, {U,V,X,Y}) = {A+U,B+V,C+X,D+Y} */
int4x8 add_i4x8(int4x8 x, int4x8 y);

/* Subtraction:  sub_i4x8({A,B,C,D}, {U,V,X,Y}) = {A-U,B-V,C-X,D-Y} */
int4x8 sub_i4x8(int4x8 x, int4x8 y);

/* Sideways sum: sum_i4x8({A,B,C,D}) = A+B+C+D
   Note that this operation produces a single 32-bit integer result. */
int sum_i4x8(int4x8 x);


/* Packing and unpacking */

/* Compact a single 4x16-bit integer value into a 4x8 structure.
   The high order 8 bits of each original 16-bit value are lost.
       compact_to_i4x8({A_16,B_16,C_16,D_16}) = {A_8,B_8,C_8,D_8} */
int4x8 compact_to_i4x8(int4x16 input);

#define compact_to_i4x8_from_i32(llo,lhi,hlo,hhi) \
  compact_to_i4x8(compose_64(compact_to_i2x16_from_i32(llo,lhi), \
                             compact_to_i2x16_from_i32(hlo,hhi)))

/* Expand a 4x8 integer structure into a 4x16 structure.
   Each 8-bit element is sign extended to 16 bits.
       expand_i2x16({A_8,B_8,C_8,D_8}) = {A_16,B_16,C_16,D_16} */

int4x16 expand_i4x8(int4x8 input);

extern void expand_i4x8_to_i32(int4x8 input, int *llo, int *lhi, int *hlo, int *hhi);

#define expand_i4x8_to_i32(input, llo,lhi,hlo,hhi) \
   expand_i4x16_to_i32(expand_i4x8(input), llo, lhi, hlo, hhi)

extern int part_extract(int, int);

#define llow_8(val) part_extract(val, 0 << 8 + 8)
#define lhigh_8(val) part_extract(val, 8 << 8 + 8)
#define hlow_8(val) part_extract(val, 16 << 8 + 8)
#define hhigh_8(val) part_extract(val, 24 << 8 + 8)


/*************************************************************************
 * Operations on int8x8: Eight 8-bit integers in parallel
 *************************************************************************/

int8x8 add_i8x8(int8x8 x, int8x8 y);

int8x8 sub_i8x8(int8x8 x, int8x8 y);

/*  Note that this operation produces a single 32-bit integer result. */
int sum_i8x8 (int8x8 x);

/* Packing and unpacking */

/* Create a 8x8 integer structure from two 4x8 integer structures. */
int8x8 compose_i8x8_from_i4x8(int4x8 low, int4x8 high);

#define compose_i8x8_from_i4x8(a, b)  compose_64(a, b)


/* Extract the two high or two low values from a 8x8 integer structure
   to produce an int4x8. */

int4x8 extract_low_of_i8x8(int8x8 input);
int4x8 extract_high_of_i8x8(int8x8 input);

#define extract_low_of_i8x8(a)  low_32(a)
#define extract_high_of_i8x8(a)  high_32(a)
 
#ifdef __cplusplus
}
#endif

#endif /* __I16_DEFINED */
